package io.xxx.omni.osc.sync

import com.dangdang.openplatform.openapi.sdk.ApiException
import com.dangdang.openplatform.openapi.sdk.BaseResponse
import com.dangdang.openplatform.openapi.sdk.Request
import com.dangdang.openplatform.openapi.sdk.SdkClient
import com.dangdang.openplatform.openapi.sdk.request.order.OrderCancelApplyDetailsGetRequest
import com.dangdang.openplatform.openapi.sdk.request.order.OrderDetailsGetRequest
import com.dangdang.openplatform.openapi.sdk.request.order.OrdersListGetRequest
import com.dangdang.openplatform.openapi.sdk.requestmodel.order.OrderCancelDetails
import com.dangdang.openplatform.openapi.sdk.requestmodel.order.OrderDetailsGet
import com.dangdang.openplatform.openapi.sdk.requestmodel.order.OrderListGet
import com.dangdang.openplatform.openapi.sdk.response.order.OrderCancelApplyDetailsGetResponse
import com.dangdang.openplatform.openapi.sdk.response.order.OrderDetailsGetResponse
import com.dangdang.openplatform.openapi.sdk.response.order.OrdersListGetResponse
import io.xxx.omni.osc.common.dateTimeFormatter
import io.xxx.omni.osc.common.toLocalDateTime
import io.xxx.omni.osc.domain.Document
import io.xxx.omni.osc.domain.DocumentType
import io.xxx.omni.osc.domain.PlatformIdentity
import io.xxx.omni.osc.domain.Store
import org.springframework.stereotype.Component
import java.time.LocalDateTime

/**
 * 当当
 */
// https://open.dangdang.com/index.php?c=documentCenter&f=show&page_id=89
// https://open.dangdang.com/index.php?c=documentCenter&f=show&page_id=174
@Suppress("UnstableApiUsage")
abstract class DdPorter<T : Request<R>, R : BaseResponse> : PageDocumentPorter<T, R>(), PlatformIdentity.DangDang {

    override fun getResponse(context: JobContext, pageNo: Int, hasTotal: Boolean): R {
        val (store, startTime, endTime) = context
        val client = getClient(store)
        val request = buildRequest(startTime, endTime, pageNo)
        val response: R = client.excute(request)
        if (!response.isSuccess) {
            throwException(context, request, response)
        }
        return response
    }

    protected abstract fun getClient(store: Store): SdkClient

    protected abstract fun buildRequest(
        startTime: LocalDateTime,
        endTime: LocalDateTime,
        pageNo: Int
    ): T
}

// 订单
// http://open.dangdang.com/index.php?c=documentCenterG4&f=show&page_id=132
@Component
@Suppress("UnstableApiUsage")
class DdTradePorter : DdPorter<OrdersListGetRequest, OrdersListGetResponse>() {

    override val permitsPerMinutes = 500

    override val documentType = DocumentType.TRADE

    override fun getClient(store: Store): SdkClient =
        applicationContext.getBean("${store.pid}ClientV2${store.id}", SdkClient::class.java)

    override fun getCount(context: JobContext, response: OrdersListGetResponse): Int {
        return response.totalInfo.orderCount ?: 0
    }

    override fun buildDocuments(context: JobContext, response: OrdersListGetResponse): List<Document> {
        return response
            .orderList
            .map {
                val request = OrderDetailsGetRequest()
                val detailsGet = OrderDetailsGet()
                detailsGet.o = it.orderID.toString()
                detailsGet.outerOrderID = it.outerOrderID
                request.orderDetailsGet = detailsGet
                val client = getClient(context.store)
                var detailResponse: OrderDetailsGetResponse? = null
                try {
                    detailResponse = client.excute(request)
                } catch (e: ApiException) {
                    throwException(context, request, e)
                }
                detailResponse!!
            }
            .map { value ->
                val sn = value.orderID.toString()
                val status = value.orderStatus.toString()
                val modified = value.lastModifyTime.toLocalDateTime()
                Document(sn, status, modified, value)
            }
    }

    override fun buildRequest(startTime: LocalDateTime, endTime: LocalDateTime, pageNo: Int): OrdersListGetRequest {
        val request = OrdersListGetRequest()
        val get = OrderListGet()
        get.os = "9999"
        get.p = pageNo
        get.pageSize = pageSize
        get.lastModifyTime_start = startTime.format(dateTimeFormatter)
        get.lastModifyTime_end = endTime.format(dateTimeFormatter)
        request.orderListGet = get
        return request
    }
}

// 退单
// http://open.dangdang.com/index.php?c=documentCenterG4&f=show&page_id=138
@Component
@Suppress("UnstableApiUsage")
class DdRefundPorter : DdPorter<OrderCancelApplyDetailsGetRequest, OrderCancelApplyDetailsGetResponse>() {

    override val permitsPerMinutes = 30

    override val documentType = DocumentType.REFUND

    override fun getClient(store: Store): SdkClient =
        applicationContext.getBean("${store.pid}ClientV1${store.id}", SdkClient::class.java)

    override fun getCount(context: JobContext, response: OrderCancelApplyDetailsGetResponse): Int {
        return response.orderCancelApplyRemote.size
    }

    override fun buildDocuments(context: JobContext, response: OrderCancelApplyDetailsGetResponse): List<Document> {
        return response
            .orderCancelApplyRemote
            .map { value ->
                val sn = value.applyId.toString()
                val rsn = value.orderId.toString()
                val status = value.applyStatus.toString()
                val modified = value.lastChangeDate.toLocalDateTime()
                Document(sn, rsn, status, modified, value)
            }
    }

    override fun buildRequest(
        startTime: LocalDateTime,
        endTime: LocalDateTime,
        pageNo: Int
    ): OrderCancelApplyDetailsGetRequest {
        val request = OrderCancelApplyDetailsGetRequest()
        val od = OrderCancelDetails()
        od.creationDateBegin = startTime.format(dateTimeFormatter)
        od.creationDateEnd = endTime.format(dateTimeFormatter)
        request.orderCancelDetails = od
        return request
    }
}